<template>
  <div class="login_body">
    <!-- 用户名密码登录 -->
    <div class="login">
      <div class="loginType">
        <span
          :class="{ active_type: loginTypeIndex === index }"
          @click="chooseLoginType(index)"
          v-for="(item, index) in loginTypeList"
          :key="index"
          >{{ item }}</span
        >
      </div>

      <template v-if="loginTypeIndex !== 2">
        <div class="login_box" v-if="loginTypeIndex === 0">
          <input type="text" required v-model="loginForm.loginInput" /><label
            >邮箱{{ !isRegister ? `/手机/昵称` : "" }}</label
          >
        </div>
        <div class="login_box" v-if="loginTypeIndex === 1">
          <input
            type="text"
            required
            @blur="valitedInput('isPhonenumber', loginForm.phoneNumber)"
            v-model="loginForm.phoneNumber"
          /><label>手机</label>
        </div>
        <div class="login_box" v-if="isRegister">
          <input
            type="text"
            required
            @blur="valitedInput('nickname', loginForm.nickname)"
            v-model="loginForm.nickname"
          /><label>昵称</label>
        </div>
        <div class="login_box" v-if="loginTypeIndex === 0">
          <input
            type="password"
            @blur="valitedInput('isPassword', loginForm.password)"
            v-model="loginForm.password"
            required="required"
          /><label>密码</label>
        </div>
        <div
          class="login_box lastInput"
          v-if="isRegister || loginTypeIndex === 1"
        >
          <input
            type="password"
            v-model="loginForm.codeNumber"
            required="required"
          /><label>验证码</label>
          <span class="sendNumber" @click="handleSendNumber">{{
            isSend ? endTime + "s" : sendNumberTip
          }}</span>
        </div>

        <a href="javascript:void(0)" @click="handleLogin">
          {{ isRegister ? "注册" : "登录" }}
          <span></span>
          <span></span>
          <span></span>
          <span></span>
        </a>
      </template>

      <template v-else>
        <div class="QRcode">
          <!--扫码成功的样式-->
          <div class="QRcode_success" v-if="successShow">
            <img src="../../assets/img/login/success.png" alt="success" />
            <p>扫码成功</p>
          </div>
          <!--二维码失效的样式-->
          <div
            class="QRcode_overtime"
            @click="scanAgainScanCode"
            v-if="overtimeShow"
          >
            <p>二维码失效，点击重新获取</p>
            <img src="../../assets/img/login//reload.png" alt="reload.png" />
          </div>
          <!--真正让用户扫的二维码-->
          <img class="QRcode_img" :src="QRcode" />
        </div>
        <p class="tips">{{ tipsText }}</p>
      </template>

      <div class="bottomDesc" v-if="loginTypeIndex === 0">
        <span class="toregister" @click="handleToRegister">
          {{ isRegister ? "去登录" : "去注册" }}
        </span>
        <span class="forgetPassword">忘记密码</span>
      </div>
    </div>
  </div>
</template>

<script>
import Qs from "qs"
import ValidForm from "../../common/validForm"
import { mapState } from "vuex"

export default {
  components: {},
  data() {
    return {
      isRegister: false,
      isPassInput: [],
      loginForm: {
        loginInput: "", // 邮箱或手机号
        password: "", // 密码,
        codeNumber: "", // 验证码
        nickname: "", // 昵称
        phoneNumber: "",
      },
      scanCodeQuery: {
        socket: null,
        timerCheck: null,
        activeName: "ScanCode",
      },
      sendNumberTip: "发送验证码",
      isSend: false,
      endTime: 60,
      timeId: null,
      loginText: "登录",
      loginTypeList: ["邮箱", "手机", "扫码"],
      loginTypeIndex: 0, // 0 邮箱，1  手机  2  扫码
    }
  },
  watch: {},
  computed: {
    ...mapState([
      "WapSuccess",
      "QRcode",
      "ScanCodeShow",
      "tipsText",
      "overtimeShow",
      "successShow",
    ]),
  },
  created() {
    this.getQRcode()
  },
  mounted() {},
  methods: {
    // ------------------------  账号密码登录
    async handleSendNumber() {
      // 第一次点击或者60秒时间已过 并且是输入格式正确   在次请求发送
      if (!this.isSend && !this.isPassInput.length) {
        // 点击是否已经发送，已经发送了，60秒未过，不能点击，置灰
        delete this.loginForm.codeNumber
        // 都验证通过, 邮箱登录
        if (this.loginTypeIndex === 0) {
          const { data: res } = await this.$http.post(
            "/user/code",
            Qs.stringify(this.loginForm)
          )
          if (res.status === "fail") return this.$message.success(res.msg)
          this.$message.success("验证码发送成功")
          this.countDown()
          // 手机登录
        } else {
          const { data: res } = await this.$http.get("/user/sendSMS", {
            params: {
              phoneNumber: this.loginForm.phoneNumber,
              codeNumber: this.loginForm.codeNumber,
            },
          })
          if (res.status === "fail") return this.$message.success(res.msg)
          this.$message.success("验证码发送成功")
          this.countDown()
        }
      } else {
        this.$message.error("请输入正确的格式")
      }
    },
    // 邮箱登录，手机登录
    handleLogin() {
      if (this.isPassInput.length) return
      if (this.loginTypeIndex === 1) return this.phoneLoginHtttp() // 手机登录
      if (!this.isRegister) {
        //邮箱登录
        this.emailLoginHttp()
      } else {
        this.emailRegister() //邮箱注册
      }
    },
    async emailLoginHttp() {
      const { data: res } = await this.$http.post(
        "/user/login1",
        Qs.stringify(this.loginForm)
      )
      if (res.status === "fail") return this.$message.error(res.msg)
      console.log(`res`, res)
      window.localStorage.setItem("userInfo", JSON.stringify(res.result))
      window.localStorage.setItem("token", res.result.token)
      this.$message.success("邮箱登录成功")

      this.$router.push("/")
    },
    async emailRegister() {
      this.loginForm.code = this.loginForm.codeNumber;
      const { data: res } = await this.$http.post(
        "/user/register",
        Qs.stringify(this.loginForm)
      )
      if (res.status === "fail") return this.$message.success(res.msg)
      if (this.timeId) this.timeId = null
      this.$message.success("邮箱注册成功")
      this.isRegister = false
      if (this.timeId) {
        this.countDown()
      }
    },
    async phoneLoginHtttp() {
      const { data: res } = await this.$http.get("/user/phoneLogin", {
        params: {
          phoneNumber: this.loginForm.phoneNumber,
          codeNumber: this.loginForm.codeNumber,
        },
      })
      if (res.status === "fail") return this.$message.error(res.msg)

      this.$message.success("登录成功")
      localStorage.setItem("userInfo", JSON.stringify(res.result))
      localStorage.setItem("token", res.result.token)
      if (this.timeId) {
        this.countDown()
      }
      this.$router.push("/")
    },
    countDown() {
      this.isSend = true
      let self = this
      self.timeId = setInterval(() => {
        self.endTime--
        if (self.endTime === -1) {
          self.endTime = 60
          self.timeId = null
          this.isSend = false
        }
      }, 1000)
    },
    handleToRegister() {
      Object.keys(this.loginForm).forEach((key) => {
        this.loginForm[key] = ""
      })
      this.isRegister = !this.isRegister
    },
    // ------------------------ 扫码登录
    // 进入扫码登录
    getScanOperate() {
      console.log(`扫码登录`)
    },
    // 获取二维码
    getQRcode() {
      this.$store.dispatch("getQRcode")
      // 获取二维码之后，每隔一秒向服务器询问，手机是否扫码成功
      this.scanCodeQuery.timerCheck = setInterval(
        () => this.checkScanCode(),
        1000
      )
    },
    chooseLoginType(index) {
      this.isRegister = false
      this.loginTypeIndex = index
      Object.keys(this.loginForm).forEach((key) => {
        this.loginForm[key] = ""
      })
      if (index === 2) {
        this.getScanOperate()
      }
    },
    // 验证输入框是否合法
    valitedInput(str, value) {
      let validForm = new ValidForm()

      if (!validForm[str](value)) {
        !this.isPassInput.includes(str) && this.isPassInput.push(str)
        this.$message.error("输入格式错误")
      } else {
        this.isPassInput.includes(str) &&
          this.isPassInput.splice(this.isPassInput.indexOf(str), 1)
      }
    },
    checkScanCode() {
      // 扫码成功
      if (this.$store.state.successShow || this.$store.state.overtimeShow) {
        clearInterval(this.timerCheck) // 扫码成功，清除定时器，不再询问服务器
      }
      this.$store.dispatch("checkScanCode", this.$store.state.uuid)
    },
    // 二维码失效后，用户点击二维码重新获取二维码的事件
    AgainScanCode() {
      this.$store.commit("AgainScanCode")
      this.getQRcode()
    },
  },
}
</script>
<style lang="less" scoped>
.loginBtn {
  width: 70px;
  padding: 5px 0;
}
.login_body {
  /* 弹性布局 让页面元素垂直+水平居中 */
  display: flex;
  justify-content: center;
  align-items: center;
  /* 让页面始终占浏览器可视区域总高度 */
  height: 100vh;
  /* 背景渐变色 */
  background: linear-gradient(rgb(82, 160, 163), #73af96);
  // background: url('../img/login/login.jpg') no-repeat right top;

  .login {
    /* 弹性布局 让子元素称为弹性项目 */
    display: flex;
    /* 让弹性项目垂直排列 原理是改变弹性盒子的主轴方向 父元素就是弹性盒子 现在改变后的主轴方向是向下了 */
    flex-direction: column;
    /* 让弹性项目在交叉轴方向水平居中 现在主轴的方向是向下 交叉轴的方向是与主轴垂直 交叉轴的方向是向右 */
    align-items: center;
    width: 400px;
    padding: 40px;
    background-color: rgba(0, 0, 0, 0.2);
    box-shadow: 0 15px 25px rgba(0, 0, 0, 0.4);
    .loginType {
      width: 100%;
      display: flex;
      justify-content: space-around;
      color: white;
      font-size: 15px;
      margin-bottom: 30px;
      .active_type {
        color: white;
      }
      span {
        cursor: pointer;
        color: #929797;
        &:hover {
          color: white;
        }
      }
    }
    .login_box {
      /* 相对定位 */
      position: relative;
      width: 100%;
      .sendNumber {
        position: absolute;
        top: 0;
        right: -37%;
        padding: 10px 5px;
        background: white;
        border-radius: 4px;
        cursor: pointer;
      }
      input {
        /* 清除input框自带的边框和轮廓 */
        outline: none;
        border: none;
        width: 100%;
        padding: 10px 0;
        margin-bottom: 30px;
        color: #fff;
        font-size: 16px;
        border-bottom: 1px solid #fff;
        /* 背景颜色为透明色 */
        background-color: transparent;
      }
      label {
        position: absolute;
        top: 0;
        left: 0;
        padding: 10px 0;
        color: #fff;
        /* 这个属性的默认值是auto 默认是这个元素可以被点击 但是如果我们写了none 就是这个元素不能被点击 , 就好像它可见但是不能用 可望而不可即 */
        /* 这个就是两者的区别 */
        pointer-events: none;
        /* 加个过渡 */
        transition: all 0.5s;
      }
      input:focus + label,
      input:valid + label {
        top: -20px;
        color: #03e9f4;
        font-size: 12px;
      }
    }
    a {
      overflow: hidden;
      position: relative;
      padding: 10px 20px;
      color: #03e9f4;
      /* 取消a表现原有的下划线 */
      text-decoration: none;
      /* 同样加个过渡 */
      transition: all 0.5s;
      &:hover {
        color: #fff;
        border-radius: 5px;
        background-color: #03e9f4;
        box-shadow: 0 0 5px #03e9f4, 0 0 25px #03e9f4, 0 0 50px #03e9f4,
          0 0 100px #03e9f4;
      }
      span:first-child {
        top: 0;
        left: -100%;
        width: 100%;
        height: 2px;
        /* to right 就是往右边 下面的同理 */
        background: linear-gradient(to right, transparent, #03e9f4);
        /* 动画 名称 时长 linear是匀速运动 infinite是无限次运动 */
        animation: move1 1s linear infinite;
      }
      span:nth-child(2) {
        right: 0;
        top: -100%;
        width: 2px;
        height: 100%;
        background: linear-gradient(transparent, #03e9f4);
        /* 这里多了个0.25s其实是延迟时间 */
        animation: move2 1s linear 0.25s infinite;
      }
      span:nth-child(3) {
        right: -100%;
        bottom: 0;
        width: 100%;
        height: 2px;
        background: linear-gradient(to left, transparent, #03e9f4);
        animation: move3 1s linear 0.5s infinite;
      }
      span:last-child {
        left: 0;
        bottom: -100%;
        width: 2px;
        height: 100%;
        background: linear-gradient(#03e9f4, transparent);
        animation: move4 1s linear 0.75s infinite;
      }
      span {
        position: absolute;
      }
    }
    .lastInput {
      width: 73%;
      align-self: flex-start;
    }
    .bottomDesc {
      width: 100%;
      display: flex;
      justify-content: space-between;
      span {
        color: white;
        cursor: pointer;
      }
    }

    //扫码登录
    .QRcode {
      width: 240px;
      height: 240px;
      position: relative;
      .QRcode_overtime {
        display: flex;
        align-items: center;
        justify-content: center;
        flex-direction: column;
        position: absolute;
        width: 100%;
        height: 100%;
        left: 0;
        top: 0;
        background: rgba(0, 0, 0, 0.68);
        color: #fff;
        text-align: center;
        z-index: 2;
        font-size: 18px;
        cursor: pointer;
        img {
          width: 40px;
          height: 40px;
          margin-top: 15px;
        }
      }
      .QRcode_success {
        display: flex;
        align-items: center;
        justify-content: center;
        flex-direction: column;
        position: absolute;
        width: 100%;
        height: 100%;
        left: 0;
        top: 0;
        background: rgba(0, 0, 0, 0.68);
        color: #fff;
        text-align: center;
        z-index: 3;
        font-size: 18px;
      }
      .QRcode_img {
        width: 100%;
        height: 100%;
        position: absolute;
        z-index: 1;
        left: 0;
        top: 0;
      }
    }
    .tips {
      margin-top: 10px;
      color: white;
    }
  }
}
/* :focus 选择器是当input获得焦点是触发的样式 + 是相邻兄弟选择器 去找与input相邻的兄弟label */
/* :valid 选择器是判断input框的内容是否合法,如果合法会执行下面的属性代码,不合法就不会执行,我们刚开始写布局的时候给input框写了required 我们删掉看对比 当没有required的话input框的值就会被认为一直合法,所以一直都是下方的样式 ,但是密码不会,密码框内的值为空,那么这句话局不合法,required不能为空 当我们给密码框写点东西的时候才会执行以下代码*/
@keyframes move1 {
  0% {
    left: -100%;
  }
  50%,
  100% {
    left: 100%;
  }
}
@keyframes move2 {
  0% {
    top: -100%;
  }
  50%,
  100% {
    top: 100%;
  }
}
@keyframes move3 {
  0% {
    right: -100%;
  }
  50%,
  100% {
    right: 100%;
  }
}
@keyframes move4 {
  0% {
    bottom: -100%;
  }
  50%,
  100% {
    bottom: 100%;
  }
}
</style>
